﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeGeneratorBootstrap.ClassServices;
using CodeGeneratorBootstrap.Generators;
using CodeGeneratorBootstrap.Util;

namespace CodeGeneratorBootstrap.Models
{
    public class ClassModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<AttributeModel> _attributes;
        public List<ButtonModel> Buttons;
        public int ProjectId { get; set; }
        public ClassTypeModel MultiDimensionStyle { get; set; }
        public List<ClassModel> ParentClass { get; set; }
        public List<ClassModel> ChildrenClass { get; set; }

        //[ding Start]
        public List<LayoutSectionModel> LayoutSection;
        //[Ding Stop]

        // Start add for summary field

        public List<AttributeModel> GetSummaryAttrAtParentByChildClass(ClassModel ChildClass)
        {
            var objResult = new List<AttributeModel>();

            if (ChildClass.ParentClass.Count() > 0)
            {
                string[] split = { "$", ".", " " };
                string[] splitFormula;
                Int64 childClassIdForSummary;

                foreach (var parentClass in ChildClass.ParentClass)
                {
                    var summaryAttributeList = parentClass.GetAttributes().FindAll(x => x.DataType.Name == "Summary-Sum" ||
                                               x.DataType.Name == "Summary-Count" ||
                                               x.DataType.Name == "Summary-Min" ||
                                               x.DataType.Name == "Summary-Max");

                    if (summaryAttributeList.Count() > 0)
                    {
                        foreach (var summaryAttrItem in summaryAttributeList)
                        {
                            //Split formula of specific summary attribute
                            splitFormula = summaryAttrItem.Formula.Split(split, StringSplitOptions.RemoveEmptyEntries);
                            childClassIdForSummary = Convert.ToInt64(splitFormula[0]);
                            if (ChildClass.Id == childClassIdForSummary)
                            {
                                objResult.Add(summaryAttrItem);
                            }
                        }
                    }
                }
            }
            return objResult;
        }
        private List<AttributeModel> GetDisplayInGridAttribute(List<AttributeModel> attributeList)
        {
            var objList = new List<AttributeModel>();
            var attrForLooping = attributeList.AsEnumerable().Where(x => x.DisplayLengthInGrid > 0);
            foreach (var attr in attrForLooping)
            {
                if (attr.DisplayLengthInGrid > 0 && attr.DataType.Name != "Lookup Table" && attr.FieldType.Name != "Image")
                {
                    objList.Add(attr);
                }
                else if (attr.DisplayLengthInGrid > 0 && attr.DataType.Name == "Lookup Table" && attr.FieldType.Name != "Image")
                {
                    var lookupModelList = attr.GetLookupModel().AsEnumerable().Where(x => x.DisplayLengthInGrid > 0); //.Find(x => x.DisplayLengthInGrid > 0);
                    if (lookupModelList != null && lookupModelList.Count() > 0)
                    {
                        foreach (var lookupModel in lookupModelList)
                        {
                            var destAttr = lookupModel.DestAttribute;
                            if (destAttr.DisplayLengthInGrid > 0)
                            {
                                objList.Add(destAttr);
                            }
                        }

                    }
                }
            }

            return objList;
        }
        public string GetFooterRecordForSummaryFieldByChildClass(ClassModel childClassModel, List<AttributeModel> summaryAttributeOfParentClass)
        {
            var footerRecordPreStr = "'<tr><td><b>Total</b></td>";
            var footerRecordPostStr = "</tr>'";
            //var colspanCount = 0;
            string[] split = { "$", ".", " " };
            var matchFlag = 0;

            // Get summary attribute list only come from child class model parameter
            var summaryAttrListFromInputChildClass =
                summaryAttributeOfParentClass.FindAll(x => Convert.ToInt32(x.Formula.Split(split, StringSplitOptions.RemoveEmptyEntries)[0]) == childClassModel.Id);
            var ChildAttrDisplayIngrid = GetDisplayInGridAttribute(childClassModel.GetAttributes()); // childClassModel.GetAttributes().FindAll(x => x.DisplayLengthInGrid != 0);

            var summaryAttrListForDisplayOnTotalRecord = summaryAttrListFromInputChildClass.FindAll(x => x.DataType.Name == "Summary-Sum" || x.DataType.Name == "Summary-Count");
            bool isSetNumberFormat;
            bool isNumericAttribute;
            foreach (var attr in ChildAttrDisplayIngrid /*childClassModel._attributes.FindAll(x => x.DisplayLengthInGrid != 0).OrderBy(m=>m.SeqNo)*/ )
            {
                foreach (var summaryAttr in summaryAttrListForDisplayOnTotalRecord)
                {
                    //Split formula of specific summary attribute
                    var splitFormula = summaryAttr.Formula.Split(split, StringSplitOptions.RemoveEmptyEntries);

                    //Extract ID of Child class's attribute from Parent class's Summary attribute
                    var sourceAttrToSummary_Id = Convert.ToInt32(splitFormula[1]);

                    if (attr.Id == sourceAttrToSummary_Id)  // If current child attribute id == id extracted from formula
                    {
                        //   FormatNumberWithCommaandDecimalPlace(@Model.GrandTotal1,"00.000")
                        isSetNumberFormat = !String.IsNullOrWhiteSpace(attr.NumberFormat);
                        isNumericAttribute = DataTypeMapper.isNumericDataType(attr);
                        if (isNumericAttribute)
                        {

                            footerRecordPreStr = isSetNumberFormat ? footerRecordPreStr + "<td class=\"word_wrap_number\"><b>' + " + "FormatNumberWithCommaandDecimalPlace(@Model." + summaryAttr.Name.ToString() + ",\"" + attr.NumberFormat + "\")+'</b></td>" : footerRecordPreStr + "<td class=\"word_wrap_number\"><b>' + " + "@Model." + summaryAttr.Name.ToString() + "+'</b></td>";
                        }
                        else
                        {
                            footerRecordPreStr = footerRecordPreStr + "<td><b>' + " + "@Model." + summaryAttr.Name.ToString() + "+'</b></td>";

                        }


                        matchFlag = 1;
                        summaryAttrListFromInputChildClass.Remove(summaryAttr);
                        break;
                    }
                    else
                    {
                        matchFlag = 0;
                    }
                }// end each child 

                if (matchFlag == 0) // if ((matchFlag != 1 && summaryAttrListFromInputChildClass.Count() != 0) || (summaryAttrListFromInputChildClass.Count() == 0))
                {
                    footerRecordPreStr = footerRecordPreStr + "<td></td>";
                }

            }

            footerRecordPreStr = footerRecordPreStr + footerRecordPostStr;
            return footerRecordPreStr;
        }


        public AttributeModel GetMasterAttributeForSummaryByChildClass(ClassModel childClassModel)
        {
            var SummaryChildClassList = _attributes.FindAll(x => x.IsMasterDetail);
            if (SummaryChildClassList != null && SummaryChildClassList.Count() != 0)
            {
                foreach (var attributeModel in SummaryChildClassList)
                {
                    var DestClassId = Generator.GetDestinationClassByAttribute(attributeModel).Id;

                    if (DestClassId == childClassModel.Id)
                    {
                        return attributeModel;

                    }

                }
                return null;
            }
            else
            {
                return null;
            }

        }
        // Edit at 20140420 
        // For Service.svc.cs
        public List<AttributeModel> GetSummaryAttributeByChildClass(ClassModel childClass) // Return all attribute that's summary-rollup field
        {
            var summaryAttribute = _attributes.FindAll(x => x.DataType.Name == "Summary-Sum" ||
                                                x.DataType.Name == "Summary-Count" ||
                                                x.DataType.Name == "Summary-Min" ||
                                                x.DataType.Name == "Summary-Max");
            if (summaryAttribute.Count() != 0 && summaryAttribute != null)
            {
                var resultList = new List<AttributeModel>();

                foreach (var attr in summaryAttribute)
                {
                    if (attr.AttributeForSummary.ClassModel.Id == childClass.Id)
                    {
                        resultList.Add(attr);
                    }
                }
                return summaryAttribute;
            }
            else
            {
                return null;
            }
        }

        public List<AttributeModel> GetCalculationAttribute() // Return all attribute that's summary-rollup field
        {
            var calculationAttribute = _attributes.FindAll(x => x.DataType.Name == "Summary-Sum" ||
                                                x.DataType.Name == "Summary-Count" ||
                                                x.DataType.Name == "Summary-Min" ||
                                                x.DataType.Name == "Summary-Max");
            if (calculationAttribute.Count() != 0 && calculationAttribute != null)
            {

                return calculationAttribute;
            }
            else
            {
                return null;
            }
        }

        public List<ClassModel> GetAllChildClassForSummary()
        {
            var summaryAttribute = _attributes.FindAll(x => x.DataType.Name == "Summary-Sum" ||
                                                x.DataType.Name == "Summary-Count" ||
                                                x.DataType.Name == "Summary-Min" ||
                                                x.DataType.Name == "Summary-Max");
            if (summaryAttribute.Count() != 0 && summaryAttribute != null)
            {
                var resultList = new List<ClassModel>();
                var childClassAlreadyInList = new List<ClassModel>();
                foreach (var attr in summaryAttribute)
                {
                    if (childClassAlreadyInList.FindAll(x => x.Id == attr.AttributeForSummary.ClassModel.Id).Count() == 0)
                    {
                        resultList.Add(attr.AttributeForSummary.ClassModel);
                    }
                }

                return resultList;
            }
            else
            {
                return null;
            }

        }
        // End add for summary field






        internal ClassModel(ClassModelDto dto)
        {
            Id = dto.Id;
            Name = dto.Name;
            ProjectId = dto.ProjectId;
            MultiDimensionStyle = new ClassTypeModel(dto.MultiDimensionStyle);
            _attributes = new List<AttributeModel>();
            Buttons = new List<ButtonModel>();

            if (dto.Attributes != null)
                //Soravit 08/05/2014 Add Sort by SeqNo
                foreach (AttributeModelDto attridto in dto.Attributes.OrderBy(o => o.SeqNo).ToList())
                {
                    if (attridto.DataType.Name.Equals("Button") || attridto.FieldType.Name.Equals("Button"))
                    {
                        ButtonModel buttonModel = new ButtonModel(attridto);
                        this.Buttons.Add(buttonModel);
                    }
                    else
                    {
                        AttributeModel attributeModel = new AttributeModel(attridto);
                        this._attributes.Add(attributeModel);
                    }
                }
            //[Ding Start]

            if (dto.LayoutSections != null)
            {
                this.LayoutSection = new List<LayoutSectionModel>();

                foreach (LayoutSectionModelDto LayoutSection in dto.LayoutSections)
                {
                    this.LayoutSection.Add(new LayoutSectionModel(LayoutSection));
                }
            }

            //[Ding stop]
        }

        internal void SetAttributes(List<AttributeModelDto> list)
        {
            _attributes = new List<AttributeModel>();
            Buttons = new List<ButtonModel>();

            if (list != null)
                //Soravit 08/05/2014 Add Sort by SeqNo
                foreach (AttributeModelDto attridto in list.OrderBy(o => o.SeqNo).ToList())
                {
                    if (attridto.DataType.Name.Equals("Button") || attridto.FieldType.Name.Equals("Button"))
                    {
                        ButtonModel buttonModel = new ButtonModel(attridto);
                        this.Buttons.Add(buttonModel);
                    }
                    else
                    {
                        AttributeModel attributeModel = new AttributeModel(attridto);
                        this._attributes.Add(attributeModel);
                    }
                }
        }

        public ClassModel()
        {
            _attributes = new List<AttributeModel>();
        }

        public void AddAttribute(AttributeModel attribute)
        {
            _attributes.Add(attribute);
        }

        public List<AttributeModel> GetAttributes()
        {
            return _attributes;
        }

        public ClassModel GetAllPrimaryKey()  // GetAllPrimaryKey() คืออะไร
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.Pk == true);

            return newDto;
        }

        public ClassModel GetAllSearchable()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.Search == true);

            return newDto;
        }

        public ClassModel GetAllDisplay()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.Display == true);

            return newDto;
        }

        public ClassModel GetAllDisplayInGrid()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.DisplayLengthInGrid > 0);

            return newDto;
        }

        public ClassModel GetAllNotNullable()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.Nullable == false);

            return newDto;
        }

        public ClassModel GetAllNullable()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.Nullable == true);

            return newDto;
        }

        /*public ClassModel GetAllDataType(int dataTypeId)
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.DataType.TypeId == dataTypeId);

            return newDto;
        }

        public ClassModel GetAllFieldType(int fieldTypeId)
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.FieldType.TypeId == fieldTypeId);

            return newDto;
        }*/

        public ClassModel GetAllSearchResult()
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.LinkEdit == true);

            return newDto;
        }

        public ClassModel GetAllDateTime() //Apple Add Method
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.DataType.Name == "DateTime");

            return newDto;
        }
        public ClassModel GetAllLookup() //Apple Add Method
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.IsLookup);

            return newDto;
        }

        public bool IsLookup(List<LookupClassModel> list)
        {
            foreach (AttributeModel a in _attributes)
            {
                if (a.GetLookup(list).Id > 0)
                    return true;
            }
            return false;
        }

        public ClassModel GetAllMasterDetail() //Wee
        {
            ClassModel newDto = new ClassModel();
            newDto.Id = this.Id;
            newDto.Name = this.Name;

            newDto._attributes = _attributes.FindAll(a => a.IsMasterDetail);

            return newDto;
        }

        //Weerachai 12-01-2014
        private List<LookupModel> lookupModels = null;
        //Soravit 11-2-2014
        /*public List<LookupModel> GetLookupModelByDestClass()
        {
            if (this.lookupModels == null)
                this.lookupModels = Generator.GetLookupModelByDestClass(this.Id);
            return this.lookupModels;
        }*/
        public List<LookupModel> GetLookupModelByDestClass()
        {
            if (this.lookupModels == null)
            {
                if (ChildrenClass.Count > 0)
                {
                    foreach (AttributeModel attr in ChildrenClass[0]._attributes)
                    {
                        if (attr.IsLookup && attr.LookupClass.Id == this.Id)
                        {
                            this.lookupModels = attr.GetLookupModel();
                            break;
                        }
                    }
                }
            }
            return this.lookupModels;
        }



    }
}
